// -*- mode:c++ -*-

// Copyright (c) 2010-2013,2016,2018-2019 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder.  You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

output header {{

template <class Micro>
class VfpMacroRegRegOp : public VfpMacroOp
{
  public:
    VfpMacroRegRegOp(ExtMachInst _machInst, RegIndex _dest,
                     RegIndex _op1, bool _wide) :
        VfpMacroOp("VfpMacroRegRegOp", _machInst, No_OpClass, _wide)
    {
        numMicroops = machInst.fpscrLen + 1;
        assert(numMicroops > 1);
        microOps = new StaticInstPtr[numMicroops];
        for (unsigned i = 0; i < numMicroops; i++) {
            VfpMicroMode mode = VfpMicroop;
            if (i == 0)
                mode = VfpFirstMicroop;
            else if (i == numMicroops - 1)
                mode = VfpLastMicroop;
            microOps[i] = new Micro(_machInst, _dest, _op1, mode);
            nextIdxs(_dest, _op1);
        }
    }
};

template <class VfpOp>
StaticInstPtr
decodeVfpRegRegOp(ExtMachInst machInst,
        RegIndex dest, RegIndex op1, bool wide)
{
    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
        return new VfpOp(machInst, dest, op1);
    } else {
        return new VfpMacroRegRegOp<VfpOp>(machInst, dest, op1, wide);
    }
}

template <class Micro>
class VfpMacroRegImmOp : public VfpMacroOp
{
  public:
    VfpMacroRegImmOp(ExtMachInst _machInst, RegIndex _dest, uint64_t _imm,
                     bool _wide) :
        VfpMacroOp("VfpMacroRegImmOp", _machInst, No_OpClass, _wide)
    {
        numMicroops = machInst.fpscrLen + 1;
        microOps = new StaticInstPtr[numMicroops];
        for (unsigned i = 0; i < numMicroops; i++) {
            VfpMicroMode mode = VfpMicroop;
            if (i == 0)
                mode = VfpFirstMicroop;
            else if (i == numMicroops - 1)
                mode = VfpLastMicroop;
            microOps[i] = new Micro(_machInst, _dest, _imm, mode);
            nextIdxs(_dest);
        }
    }
};

template <class VfpOp>
StaticInstPtr
decodeVfpRegImmOp(ExtMachInst machInst,
        RegIndex dest, uint64_t imm, bool wide)
{
    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
        return new VfpOp(machInst, dest, imm);
    } else {
        return new VfpMacroRegImmOp<VfpOp>(machInst, dest, imm, wide);
    }
}

template <class Micro>
class VfpMacroRegRegImmOp : public VfpMacroOp
{
  public:
    VfpMacroRegRegImmOp(ExtMachInst _machInst, RegIndex _dest,
                        RegIndex _op1, uint64_t _imm, bool _wide) :
        VfpMacroOp("VfpMacroRegRegImmOp", _machInst, No_OpClass, _wide)
    {
        numMicroops = machInst.fpscrLen + 1;
        microOps = new StaticInstPtr[numMicroops];
        for (unsigned i = 0; i < numMicroops; i++) {
            VfpMicroMode mode = VfpMicroop;
            if (i == 0)
                mode = VfpFirstMicroop;
            else if (i == numMicroops - 1)
                mode = VfpLastMicroop;
            microOps[i] = new Micro(_machInst, _dest, _op1, _imm, mode);
            nextIdxs(_dest, _op1);
        }
    }
};

template <class VfpOp>
StaticInstPtr
decodeVfpRegRegImmOp(ExtMachInst machInst, RegIndex dest,
                     RegIndex op1, uint64_t imm, bool wide)
{
    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
        return new VfpOp(machInst, dest, op1, imm);
    } else {
        return new VfpMacroRegRegImmOp<VfpOp>(machInst, dest, op1, imm, wide);
    }
}

template <class Micro>
class VfpMacroRegRegRegOp : public VfpMacroOp
{
  public:
    VfpMacroRegRegRegOp(ExtMachInst _machInst, RegIndex _dest,
                        RegIndex _op1, RegIndex _op2, bool _wide) :
        VfpMacroOp("VfpMacroRegRegRegOp", _machInst, No_OpClass, _wide)
    {
        numMicroops = machInst.fpscrLen + 1;
        microOps = new StaticInstPtr[numMicroops];
        for (unsigned i = 0; i < numMicroops; i++) {
            VfpMicroMode mode = VfpMicroop;
            if (i == 0)
                mode = VfpFirstMicroop;
            else if (i == numMicroops - 1)
                mode = VfpLastMicroop;
            microOps[i] = new Micro(_machInst, _dest, _op1, _op2, mode);
            nextIdxs(_dest, _op1, _op2);
        }
    }
};

template <class VfpOp>
StaticInstPtr
decodeVfpRegRegRegOp(ExtMachInst machInst, RegIndex dest,
                     RegIndex op1, RegIndex op2, bool wide)
{
    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
        return new VfpOp(machInst, dest, op1, op2);
    } else {
        return new VfpMacroRegRegRegOp<VfpOp>(machInst, dest, op1, op2, wide);
    }
}
}};

let {{

    header_output = ""
    decoder_output = ""
    exec_output = ""

    vmsrCode = vmsrEnabledCheckCode + '''
    MiscDest = Op1;
    '''

    vmsrIop = ArmInstObjParams("vmsr", "Vmsr", "FpRegRegImmOp",
                               { "code": vmsrCode,
                                 "predicate_test": predicateTest,
                                 "op_class": "SimdFloatMiscOp" },
                                ["IsSerializeAfter","IsNonSpeculative"])
    header_output += FpRegRegImmOpDeclare.subst(vmsrIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vmsrIop);
    exec_output += PredOpExecute.subst(vmsrIop);

    vmsrFpscrCode = vmsrEnabledCheckCode + '''
    Fpscr = Op1 & ~FpCondCodesMask;
    FpCondCodes = Op1 & FpCondCodesMask;
    '''
    vmsrFpscrIop = ArmInstObjParams("vmsr", "VmsrFpscr", "FpRegRegOp",
                                    { "code": vmsrFpscrCode,
                                      "predicate_test": predicateTest,
                                      "op_class": "SimdFloatMiscOp" },
                                    ["IsSerializeAfter","IsNonSpeculative",
                                     "IsSquashAfter"])
    header_output += FpRegRegOpDeclare.subst(vmsrFpscrIop);
    decoder_output += FpRegRegOpConstructor.subst(vmsrFpscrIop);
    exec_output += PredOpExecute.subst(vmsrFpscrIop);

    vmrsCode = vmrsEnabledCheckCode + '''
    CPSR cpsr = Cpsr;
    if (!isSecure(xc->tcBase()) && (cpsr.mode != MODE_HYP)) {
        HCR hcr = Hcr;
        bool hypTrap = false;
        auto *isa = static_cast<ArmISA::ISA *>(xc->tcBase()->getIsaPtr());
        switch (isa->flattenMiscIndex(op1)) {
          case MISCREG_FPSID:
            hypTrap = hcr.tid0;
            break;
          case MISCREG_MVFR0:
          case MISCREG_MVFR1:
            hypTrap = hcr.tid3;
            break;
        }
        if (hypTrap) {
            return std::make_shared<HypervisorTrap>(machInst, imm,
                ExceptionClass::TRAPPED_CP10_MRC_VMRS);
        }
    }
    Dest = MiscOp1;
    '''

    vmrsIop = ArmInstObjParams("vmrs", "Vmrs", "FpRegRegImmOp",
                               { "code": vmrsCode,
                                 "predicate_test": predicateTest,
                                 "op_class": "SimdFloatMiscOp" },
                               ["IsSerializeBefore"])
    header_output += FpRegRegImmOpDeclare.subst(vmrsIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vmrsIop);
    exec_output += PredOpExecute.subst(vmrsIop);

    vmrsFpscrIop = ArmInstObjParams("vmrs", "VmrsFpscr", "FpRegRegOp",
                                    { "code": vmrsEnabledCheckCode + \
                                              "Dest = Fpscr | FpCondCodes;",
                                      "predicate_test": predicateTest,
                                      "op_class": "SimdFloatMiscOp" },
                                    ["IsSerializeBefore"])
    header_output += FpRegRegOpDeclare.subst(vmrsFpscrIop);
    decoder_output += FpRegRegOpConstructor.subst(vmrsFpscrIop);
    exec_output += PredOpExecute.subst(vmrsFpscrIop);

    vmrsApsrFpscrCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = FpCondCodes;
        CondCodesNZ = (fpscr.n << 1) | fpscr.z;
        CondCodesC = fpscr.c;
        CondCodesV = fpscr.v;
    '''
    vmrsApsrFpscrIop = ArmInstObjParams("vmrs", "VmrsApsrFpscr", "PredOp",
                                        { "code": vmrsApsrFpscrCode,
                                          "predicate_test": predicateTest,
                                          "op_class": "SimdFloatMiscOp" })
    header_output += BasicDeclare.subst(vmrsApsrFpscrIop);
    decoder_output += BasicConstructor.subst(vmrsApsrFpscrIop);
    exec_output += PredOpExecute.subst(vmrsApsrFpscrIop);

    vmovImmSCode = vfpEnabledCheckCode + '''
        FpDest_uw = bits(imm, 31, 0);
    '''
    vmovImmSIop = ArmInstObjParams("vmov", "VmovImmS", "FpRegImmOp",
                                   { "code": vmovImmSCode,
                                     "predicate_test": predicateTest,
                                     "op_class": "SimdFloatMiscOp" }, [])
    header_output += FpRegImmOpDeclare.subst(vmovImmSIop);
    decoder_output += FpRegImmOpConstructor.subst(vmovImmSIop);
    exec_output += PredOpExecute.subst(vmovImmSIop);

    vmovImmDCode = vfpEnabledCheckCode + '''
        FpDestP0_uw = bits(imm, 31, 0);
        FpDestP1_uw = bits(imm, 63, 32);
    '''
    vmovImmDIop = ArmInstObjParams("vmov", "VmovImmD", "FpRegImmOp",
                                   { "code": vmovImmDCode,
                                     "predicate_test": predicateTest,
                                     "op_class": "SimdFloatMiscOp" }, [])
    header_output += FpRegImmOpDeclare.subst(vmovImmDIop);
    decoder_output += FpRegImmOpConstructor.subst(vmovImmDIop);
    exec_output += PredOpExecute.subst(vmovImmDIop);

    vmovImmQCode = vfpEnabledCheckCode + '''
        FpDestP0_uw = bits(imm, 31, 0);
        FpDestP1_uw = bits(imm, 63, 32);
        FpDestP2_uw = bits(imm, 31, 0);
        FpDestP3_uw = bits(imm, 63, 32);
    '''
    vmovImmQIop = ArmInstObjParams("vmov", "VmovImmQ", "FpRegImmOp",
                                   { "code": vmovImmQCode,
                                     "predicate_test": predicateTest,
                                     "op_class": "SimdFloatMiscOp" }, [])
    header_output += FpRegImmOpDeclare.subst(vmovImmQIop);
    decoder_output += FpRegImmOpConstructor.subst(vmovImmQIop);
    exec_output += PredOpExecute.subst(vmovImmQIop);

    vmovRegSCode = vfpEnabledCheckCode + '''
        FpDest_uw = FpOp1_uw;
    '''
    vmovRegSIop = ArmInstObjParams("vmov", "VmovRegS", "FpRegRegOp",
                                   { "code": vmovRegSCode,
                                     "predicate_test": predicateTest,
                                     "op_class": "SimdFloatMiscOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vmovRegSIop);
    decoder_output += FpRegRegOpConstructor.subst(vmovRegSIop);
    exec_output += PredOpExecute.subst(vmovRegSIop);

    vmovRegDCode = vfpEnabledCheckCode + '''
        FpDestP0_uw = FpOp1P0_uw;
        FpDestP1_uw = FpOp1P1_uw;
    '''
    vmovRegDIop = ArmInstObjParams("vmov", "VmovRegD", "FpRegRegOp",
                                   { "code": vmovRegDCode,
                                     "predicate_test": predicateTest,
                                     "op_class": "SimdFloatMiscOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vmovRegDIop);
    decoder_output += FpRegRegOpConstructor.subst(vmovRegDIop);
    exec_output += PredOpExecute.subst(vmovRegDIop);

    vmovRegQCode = vfpEnabledCheckCode + '''
        FpDestP0_uw = FpOp1P0_uw;
        FpDestP1_uw = FpOp1P1_uw;
        FpDestP2_uw = FpOp1P2_uw;
        FpDestP3_uw = FpOp1P3_uw;
    '''
    vmovRegQIop = ArmInstObjParams("vmov", "VmovRegQ", "FpRegRegOp",
                                   { "code": vmovRegQCode,
                                     "predicate_test": predicateTest,
                                     "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegOpDeclare.subst(vmovRegQIop);
    decoder_output  += FpRegRegOpConstructor.subst(vmovRegQIop);
    exec_output += PredOpExecute.subst(vmovRegQIop);

    vmovCoreRegBCode = simdEnabledCheckCode + '''
        FpDest_uw = insertBits(FpDest_uw, imm * 8 + 7, imm * 8, Op1_ub);
    '''
    vmovCoreRegBIop = ArmInstObjParams("vmov", "VmovCoreRegB", "FpRegRegImmOp",
                                       { "code": vmovCoreRegBCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegImmOpDeclare.subst(vmovCoreRegBIop);
    decoder_output  += FpRegRegImmOpConstructor.subst(vmovCoreRegBIop);
    exec_output += PredOpExecute.subst(vmovCoreRegBIop);

    vmovCoreRegHCode = simdEnabledCheckCode + '''
        FpDest_uw = insertBits(FpDest_uw, imm * 16 + 15, imm * 16, Op1_uh);
    '''
    vmovCoreRegHIop = ArmInstObjParams("vmov", "VmovCoreRegH", "FpRegRegImmOp",
                                       { "code": vmovCoreRegHCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegImmOpDeclare.subst(vmovCoreRegHIop);
    decoder_output  += FpRegRegImmOpConstructor.subst(vmovCoreRegHIop);
    exec_output += PredOpExecute.subst(vmovCoreRegHIop);

    vmovCoreRegWCode = vfpEnabledCheckCode + '''
        FpDest_uw = Op1_uw;
    '''
    vmovCoreRegWIop = ArmInstObjParams("vmov", "VmovCoreRegW", "FpRegRegOp",
                                       { "code": vmovCoreRegWCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegOpDeclare.subst(vmovCoreRegWIop);
    decoder_output  += FpRegRegOpConstructor.subst(vmovCoreRegWIop);
    exec_output += PredOpExecute.subst(vmovCoreRegWIop);

    vmovRegCoreUBCode = vfpEnabledCheckCode + '''
        assert(imm < 4);
        Dest = bits(FpOp1_uw, imm * 8 + 7, imm * 8);
    '''
    vmovRegCoreUBIop = ArmInstObjParams(
            "vmov", "VmovRegCoreUB", "FpRegRegImmOp",
            { "code": vmovRegCoreUBCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreUBIop);
    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreUBIop);
    exec_output += PredOpExecute.subst(vmovRegCoreUBIop);

    vmovRegCoreUHCode = vfpEnabledCheckCode + '''
        assert(imm < 2);
        Dest = bits(FpOp1_uw, imm * 16 + 15, imm * 16);
    '''
    vmovRegCoreUHIop = ArmInstObjParams(
            "vmov", "VmovRegCoreUH", "FpRegRegImmOp",
            { "code": vmovRegCoreUHCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreUHIop);
    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreUHIop);
    exec_output += PredOpExecute.subst(vmovRegCoreUHIop);

    vmovRegCoreSBCode = vfpEnabledCheckCode + '''
        assert(imm < 4);
        Dest = sext<8>(bits(FpOp1_uw, imm * 8 + 7, imm * 8));
    '''
    vmovRegCoreSBIop = ArmInstObjParams(
            "vmov", "VmovRegCoreSB", "FpRegRegImmOp",
            { "code": vmovRegCoreSBCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreSBIop);
    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreSBIop);
    exec_output += PredOpExecute.subst(vmovRegCoreSBIop);

    vmovRegCoreSHCode = vfpEnabledCheckCode + '''
        assert(imm < 2);
        Dest = sext<16>(bits(FpOp1_uw, imm * 16 + 15, imm * 16));
    '''
    vmovRegCoreSHIop = ArmInstObjParams(
            "vmov", "VmovRegCoreSH", "FpRegRegImmOp",
            { "code": vmovRegCoreSHCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreSHIop);
    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreSHIop);
    exec_output += PredOpExecute.subst(vmovRegCoreSHIop);

    vmovRegCoreWCode = vfpEnabledCheckCode + '''
        Dest = FpOp1_uw;
    '''
    vmovRegCoreWIop = ArmInstObjParams("vmov", "VmovRegCoreW", "FpRegRegOp",
                                       { "code": vmovRegCoreWCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegOpDeclare.subst(vmovRegCoreWIop);
    decoder_output  += FpRegRegOpConstructor.subst(vmovRegCoreWIop);
    exec_output += PredOpExecute.subst(vmovRegCoreWIop);

    vmov2Reg2CoreCode = vfpEnabledCheckCode + '''
        FpDestP0_uw = Op1_uw;
        FpDestP1_uw = Op2_uw;
    '''
    vmov2Reg2CoreIop = ArmInstObjParams(
            "vmov", "Vmov2Reg2Core", "FpRegRegRegOp",
            { "code": vmov2Reg2CoreCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vmov2Reg2CoreIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vmov2Reg2CoreIop);
    exec_output += PredOpExecute.subst(vmov2Reg2CoreIop);

    vmov2Core2RegCode = vfpEnabledCheckCode + '''
        Dest_uw = FpOp2P0_uw;
        Op1_uw = FpOp2P1_uw;
    '''
    vmov2Core2RegIop = ArmInstObjParams(
            "vmov", "Vmov2Core2Reg", "FpRegRegRegOp",
            { "code": vmov2Core2RegCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatMiscOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vmov2Core2RegIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vmov2Core2RegIop);
    exec_output += PredOpExecute.subst(vmov2Core2RegIop);
}};

let {{

    header_output = ""
    decoder_output = ""
    exec_output = ""

    singleSimpleCode = vfpEnabledCheckCode + '''
        [[maybe_unused]] FPSCR fpscr = (FPSCR) FpscrExc;
        FpDest = %(op)s;
    '''
    singleCode = singleSimpleCode + '''
        FpscrExc = fpscr;
    '''
    singleTernOp = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        float cOp1 = FpOp1;
        float cOp2 = FpOp2;
        float cOp3 = FpDestP0;
        FpDestP0   = ternaryOp(fpscr, %(palam)s, %(op)s,
                               fpscr.fz, fpscr.dn, fpscr.rMode);
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    singleBinOp = "binaryOp(fpscr, FpOp1, FpOp2," + \
                "%(func)s, fpscr.fz, fpscr.dn, fpscr.rMode)"
    singleUnaryOp = "unaryOp(fpscr, FpOp1, %(func)s, fpscr.fz, fpscr.rMode)"
    doubleCode = vfpEnabledCheckCode + '''
        [[maybe_unused]] FPSCR fpscr = (FPSCR) FpscrExc;
        double dest = %(op)s;
        FpDestP0_uw = dblLow(dest);
        FpDestP1_uw = dblHi(dest);
        FpscrExc = fpscr;
    '''
    doubleTernOp = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        double cOp1  = dbl(FpOp1P0_uw, FpOp1P1_uw);
        double cOp2  = dbl(FpOp2P0_uw, FpOp2P1_uw);
        double cOp3  = dbl(FpDestP0_uw, FpDestP1_uw);
        double cDest = ternaryOp(fpscr, %(palam)s, %(op)s,
                                 fpscr.fz, fpscr.dn, fpscr.rMode);
        FpDestP0_uw  = dblLow(cDest);
        FpDestP1_uw  = dblHi(cDest);
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    doubleBinOp = '''
        binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
                        dbl(FpOp2P0_uw, FpOp2P1_uw),
                        %(func)s, fpscr.fz, fpscr.dn, fpscr.rMode);
    '''
    doubleUnaryOp = '''
        unaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw), %(func)s,
                fpscr.fz, fpscr.rMode)
    '''

    def buildTernaryFpOp(Name, base, opClass, singleOp, doubleOp, paramStr):
        global header_output, decoder_output, exec_output

        code = singleTernOp % { "op": singleOp, "palam": paramStr }
        sIop = ArmInstObjParams(Name.lower() + "s", Name + "S", base,
                { "code": code,
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])
        code = doubleTernOp % { "op": doubleOp, "palam": paramStr }
        dIop = ArmInstObjParams(Name.lower() + "d", Name + "D", base,
                { "code": code,
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])

        declareTempl     = eval(base + "Declare");
        constructorTempl = eval(base + "Constructor");

        for iop in sIop, dIop:
            header_output  += declareTempl.subst(iop)
            decoder_output += constructorTempl.subst(iop)
            exec_output    += PredOpExecute.subst(iop)

    buildTernaryFpOp("Vfma",  "FpRegRegRegOp", "SimdFloatMultAccOp",
                     "fpMulAdd<float>", "fpMulAdd<double>", " cOp1, cOp2,  cOp3" )
    buildTernaryFpOp("Vfms",  "FpRegRegRegOp", "SimdFloatMultAccOp",
                     "fpMulAdd<float>", "fpMulAdd<double>", "-cOp1, cOp2,  cOp3" )
    buildTernaryFpOp("Vfnma", "FpRegRegRegOp", "SimdFloatMultAccOp",
                     "fpMulAdd<float>", "fpMulAdd<double>", "-cOp1, cOp2, -cOp3" )
    buildTernaryFpOp("Vfnms", "FpRegRegRegOp", "SimdFloatMultAccOp",
                     "fpMulAdd<float>", "fpMulAdd<double>", " cOp1, cOp2, -cOp3" )

    def buildBinFpOp(name, Name, base, opClass, singleOp, doubleOp):
        global header_output, decoder_output, exec_output

        code = singleCode % { "op": singleBinOp }
        code = code % { "func": singleOp }
        sIop = ArmInstObjParams(name + "s", Name + "S", base,
                { "code": code,
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])
        code = doubleCode % { "op": doubleBinOp }
        code = code % { "func": doubleOp }
        dIop = ArmInstObjParams(name + "d", Name + "D", base,
                { "code": code,
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])

        declareTempl = eval(base + "Declare");
        constructorTempl = eval(base + "Constructor");

        for iop in sIop, dIop:
            header_output += declareTempl.subst(iop)
            decoder_output += constructorTempl.subst(iop)
            exec_output += PredOpExecute.subst(iop)

    buildBinFpOp("vadd", "Vadd", "FpRegRegRegOp", "SimdFloatAddOp", "fpAddS",
                 "fpAddD")
    buildBinFpOp("vsub", "Vsub", "FpRegRegRegOp", "SimdFloatAddOp", "fpSubS",
                 "fpSubD")
    buildBinFpOp("vdiv", "Vdiv", "FpRegRegRegOp", "SimdFloatDivOp", "fpDivS",
                 "fpDivD")
    buildBinFpOp("vmul", "Vmul", "FpRegRegRegOp", "SimdFloatMultOp", "fpMulS",
                 "fpMulD")

    def buildBinOp(name, base, opClass, op):
        '''
        Create backported aarch64 instructions that use fplib.

        Because they are backported, these instructions are unconditional.
        '''
        global header_output, decoder_output, exec_output
        inst_datas = [
            (
                "s",
                '''
                FpDest_uw = fplib%(op)s<>(FpOp1_uw, FpOp2_uw, fpscr);
                '''
            ),
            (
                "d",
                '''
                uint64_t op1 = ((uint64_t)FpOp1P0_uw |
                               ((uint64_t)FpOp1P1_uw << 32));
                uint64_t op2 = ((uint64_t)FpOp2P0_uw |
                               ((uint64_t)FpOp2P1_uw << 32));
                uint64_t dest = fplib%(op)s<>(op1, op2, fpscr);
                FpDestP0_uw = dest;
                FpDestP1_uw = dest >> 32;
                '''
            )
        ]
        Name = name[0].upper() + name[1:]
        declareTempl = eval(base + "Declare");
        constructorTempl = eval(base + "Constructor");
        for size_suffix, code in inst_datas:
            code = (
                '''
                FPSCR fpscr = (FPSCR)FpscrExc;
                ''' +
                code +
                '''
                FpscrExc = fpscr;
                '''
            )
            iop = ArmInstObjParams(
                name + size_suffix,
                Name + size_suffix.upper(),
                base,
                {
                    "code": code % {"op": op},
                    "op_class": opClass
                },
                []
            )
            header_output += declareTempl.subst(iop)
            decoder_output += constructorTempl.subst(iop)
            exec_output += BasicExecute.subst(iop)
    ops = [
        ("vminnm", "FpRegRegRegOp", "SimdFloatCmpOp", "MinNum"),
        ("vmaxnm", "FpRegRegRegOp", "SimdFloatCmpOp", "MaxNum"),
    ]
    for op in ops:
        buildBinOp(*op)

    def buildUnaryFpOp(name, Name, base, opClass, singleOp, doubleOp = None):
        if doubleOp is None:
            doubleOp = singleOp
        global header_output, decoder_output, exec_output

        code = singleCode % { "op": singleUnaryOp }
        code = code % { "func": singleOp }
        sIop = ArmInstObjParams(name + "s", Name + "S", base,
                { "code": code,
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])
        code = doubleCode % { "op": doubleUnaryOp }
        code = code % { "func": doubleOp }
        dIop = ArmInstObjParams(name + "d", Name + "D", base,
                { "code": code,
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])

        declareTempl = eval(base + "Declare");
        constructorTempl = eval(base + "Constructor");

        for iop in sIop, dIop:
            header_output += declareTempl.subst(iop)
            decoder_output += constructorTempl.subst(iop)
            exec_output += PredOpExecute.subst(iop)

    buildUnaryFpOp("vsqrt", "Vsqrt", "FpRegRegOp", "SimdFloatSqrtOp", "sqrtf",
                   "sqrt")

    def buildSimpleUnaryFpOp(name, Name, base, opClass, singleOp,
                             doubleOp = None):
        if doubleOp is None:
            doubleOp = singleOp
        global header_output, decoder_output, exec_output

        sIop = ArmInstObjParams(name + "s", Name + "S", base,
                { "code": singleSimpleCode % { "op": singleOp },
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])
        dIop = ArmInstObjParams(name + "d", Name + "D", base,
                { "code": doubleCode % { "op": doubleOp },
                  "predicate_test": predicateTest,
                  "op_class": opClass }, [])

        declareTempl = eval(base + "Declare");
        constructorTempl = eval(base + "Constructor");

        for iop in sIop, dIop:
            header_output += declareTempl.subst(iop)
            decoder_output += constructorTempl.subst(iop)
            exec_output += PredOpExecute.subst(iop)

    buildSimpleUnaryFpOp("vneg", "Vneg", "FpRegRegOp", "SimdFloatMiscOp",
                         "-FpOp1", "-dbl(FpOp1P0_uw, FpOp1P1_uw)")
    buildSimpleUnaryFpOp("vabs", "Vabs", "FpRegRegOp", "SimdFloatMiscOp",
                         "fabsf(FpOp1)", "fabs(dbl(FpOp1P0_uw, FpOp1P1_uw))")
    buildSimpleUnaryFpOp("vrintp", "VRIntP", "FpRegRegOp", "SimdFloatMiscOp",
        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_POSINF, false, fpscr)",
        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
        "FPRounding_POSINF, false, fpscr)"
        )
    buildSimpleUnaryFpOp("vrintm", "VRIntM", "FpRegRegOp", "SimdFloatMiscOp",
        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_NEGINF, false, fpscr)",
        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
        "FPRounding_NEGINF, false, fpscr)"
        )
    buildSimpleUnaryFpOp("vrinta", "VRIntA", "FpRegRegOp", "SimdFloatMiscOp",
        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_TIEAWAY, false, fpscr)",
        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
        "FPRounding_TIEAWAY, false, fpscr)"
        )
    buildSimpleUnaryFpOp("vrintn", "VRIntN", "FpRegRegOp", "SimdFloatMiscOp",
        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_TIEEVEN, false, fpscr)",
        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
        "FPRounding_TIEEVEN, false, fpscr)"
        )
}};

let {{

    header_output = ""
    decoder_output = ""
    exec_output = ""

    vmlaSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        float mid = binaryOp(fpscr, FpOp1, FpOp2,
                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
        FpDest = binaryOp(fpscr, FpDest, mid, fpAddS,
                fpscr.fz, fpscr.dn, fpscr.rMode);
        FpscrExc = fpscr;
    '''
    vmlaSIop = ArmInstObjParams("vmlas", "VmlaS", "FpRegRegRegOp",
                                     { "code": vmlaSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vmlaSIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vmlaSIop);
    exec_output += PredOpExecute.subst(vmlaSIop);

    vmlaDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
        double dest = binaryOp(fpscr, dbl(FpDestP0_uw, FpDestP1_uw),
                                      mid, fpAddD, fpscr.fz,
                                      fpscr.dn, fpscr.rMode);
        FpDestP0_uw = dblLow(dest);
        FpDestP1_uw = dblHi(dest);
        FpscrExc = fpscr;
    '''
    vmlaDIop = ArmInstObjParams("vmlad", "VmlaD", "FpRegRegRegOp",
                                     { "code": vmlaDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vmlaDIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vmlaDIop);
    exec_output += PredOpExecute.subst(vmlaDIop);

    vmlsSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        float mid = binaryOp(fpscr, FpOp1, FpOp2,
                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
        FpDest = binaryOp(fpscr, FpDest, -mid, fpAddS,
                fpscr.fz, fpscr.dn, fpscr.rMode);
        FpscrExc = fpscr;
    '''
    vmlsSIop = ArmInstObjParams("vmlss", "VmlsS", "FpRegRegRegOp",
                                     { "code": vmlsSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vmlsSIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vmlsSIop);
    exec_output += PredOpExecute.subst(vmlsSIop);

    vmlsDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
        double dest = binaryOp(fpscr, dbl(FpDestP0_uw, FpDestP1_uw),
                                      -mid, fpAddD, fpscr.fz,
                                      fpscr.dn, fpscr.rMode);
        FpDestP0_uw = dblLow(dest);
        FpDestP1_uw = dblHi(dest);
        FpscrExc = fpscr;
    '''
    vmlsDIop = ArmInstObjParams("vmlsd", "VmlsD", "FpRegRegRegOp",
                                     { "code": vmlsDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vmlsDIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vmlsDIop);
    exec_output += PredOpExecute.subst(vmlsDIop);

    vnmlaSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        float mid = binaryOp(fpscr, FpOp1, FpOp2,
                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
        FpDest = binaryOp(fpscr, -FpDest, -mid, fpAddS,
                fpscr.fz, fpscr.dn, fpscr.rMode);
        FpscrExc = fpscr;
    '''
    vnmlaSIop = ArmInstObjParams("vnmlas", "VnmlaS", "FpRegRegRegOp",
                                     { "code": vnmlaSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vnmlaSIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlaSIop);
    exec_output += PredOpExecute.subst(vnmlaSIop);

    vnmlaDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
        double dest = binaryOp(fpscr, -dbl(FpDestP0_uw, FpDestP1_uw),
                                      -mid, fpAddD, fpscr.fz,
                                      fpscr.dn, fpscr.rMode);
        FpDestP0_uw = dblLow(dest);
        FpDestP1_uw = dblHi(dest);
        FpscrExc = fpscr;
    '''
    vnmlaDIop = ArmInstObjParams("vnmlad", "VnmlaD", "FpRegRegRegOp",
                                     { "code": vnmlaDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vnmlaDIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlaDIop);
    exec_output += PredOpExecute.subst(vnmlaDIop);

    vnmlsSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        float mid = binaryOp(fpscr, FpOp1, FpOp2,
                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
        FpDest = binaryOp(fpscr, -FpDest, mid, fpAddS,
                fpscr.fz, fpscr.dn, fpscr.rMode);
        FpscrExc = fpscr;
    '''
    vnmlsSIop = ArmInstObjParams("vnmlss", "VnmlsS", "FpRegRegRegOp",
                                 { "code": vnmlsSCode,
                                   "predicate_test": predicateTest,
                                   "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vnmlsSIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlsSIop);
    exec_output += PredOpExecute.subst(vnmlsSIop);

    vnmlsDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
        double dest = binaryOp(fpscr, -dbl(FpDestP0_uw, FpDestP1_uw),
                                      mid, fpAddD, fpscr.fz,
                                      fpscr.dn, fpscr.rMode);
        FpDestP0_uw = dblLow(dest);
        FpDestP1_uw = dblHi(dest);
        FpscrExc = fpscr;
    '''
    vnmlsDIop = ArmInstObjParams("vnmlsd", "VnmlsD", "FpRegRegRegOp",
                                 { "code": vnmlsDCode,
                                   "predicate_test": predicateTest,
                                   "op_class": "SimdFloatMultAccOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vnmlsDIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlsDIop);
    exec_output += PredOpExecute.subst(vnmlsDIop);

    vnmulSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        FpDest = -binaryOp(fpscr, FpOp1, FpOp2, fpMulS,
                fpscr.fz, fpscr.dn, fpscr.rMode);
        FpscrExc = fpscr;
    '''
    vnmulSIop = ArmInstObjParams("vnmuls", "VnmulS", "FpRegRegRegOp",
                                 { "code": vnmulSCode,
                                   "predicate_test": predicateTest,
                                   "op_class": "SimdFloatMultOp" }, [])
    header_output  += FpRegRegRegOpDeclare.subst(vnmulSIop);
    decoder_output  += FpRegRegRegOpConstructor.subst(vnmulSIop);
    exec_output += PredOpExecute.subst(vnmulSIop);

    vnmulDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double dest = -binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
                                       dbl(FpOp2P0_uw, FpOp2P1_uw),
                                       fpMulD, fpscr.fz, fpscr.dn,
                                       fpscr.rMode);
        FpDestP0_uw = dblLow(dest);
        FpDestP1_uw = dblHi(dest);
        FpscrExc = fpscr;
    '''
    vnmulDIop = ArmInstObjParams("vnmuld", "VnmulD", "FpRegRegRegOp",
                                     { "code": vnmulDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatMultOp" }, [])
    header_output += FpRegRegRegOpDeclare.subst(vnmulDIop);
    decoder_output += FpRegRegRegOpConstructor.subst(vnmulDIop);
    exec_output += PredOpExecute.subst(vnmulDIop);
}};

let {{

    header_output = ""
    decoder_output = ""
    exec_output = ""

    vcvtUIntFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1_uw) : "m" (FpOp1_uw));
        FpDest = FpOp1_uw;
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtUIntFpSIop = ArmInstObjParams("vcvt", "VcvtUIntFpS", "FpRegRegOp",
                                      { "code": vcvtUIntFpSCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtUIntFpSIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtUIntFpSIop);
    exec_output += PredOpExecute.subst(vcvtUIntFpSIop);

    vcvtUIntFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1P0_uw) : "m" (FpOp1P0_uw));
        double cDest = (uint64_t)FpOp1P0_uw;
        __asm__ __volatile__("" :: "m" (cDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = dblLow(cDest);
        FpDestP1_uw = dblHi(cDest);
        FpscrExc = fpscr;
    '''
    vcvtUIntFpDIop = ArmInstObjParams("vcvt", "VcvtUIntFpD", "FpRegRegOp",
                                      { "code": vcvtUIntFpDCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtUIntFpDIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtUIntFpDIop);
    exec_output += PredOpExecute.subst(vcvtUIntFpDIop);

    vcvtSIntFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1_sw) : "m" (FpOp1_sw));
        FpDest = FpOp1_sw;
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtSIntFpSIop = ArmInstObjParams("vcvt", "VcvtSIntFpS", "FpRegRegOp",
                                      { "code": vcvtSIntFpSCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtSIntFpSIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtSIntFpSIop);
    exec_output += PredOpExecute.subst(vcvtSIntFpSIop);

    vcvtSIntFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1P0_sw) : "m" (FpOp1P0_sw));
        double cDest = FpOp1P0_sw;
        __asm__ __volatile__("" :: "m" (cDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = dblLow(cDest);
        FpDestP1_uw = dblHi(cDest);
        FpscrExc = fpscr;
    '''
    vcvtSIntFpDIop = ArmInstObjParams("vcvt", "VcvtSIntFpD", "FpRegRegOp",
                                      { "code": vcvtSIntFpDCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtSIntFpDIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtSIntFpDIop);
    exec_output += PredOpExecute.subst(vcvtSIntFpDIop);

    vjcvtSFixedFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        uint64_t cOp1 = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
        uint8_t nz;
        FpDest_uw = fplibFPToFixedJS(cOp1, fpscr, false, nz);
        finishVfp(fpscr, state, fpscr.fz);
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vjcvtSFixedFpDIop = ArmInstObjParams(
            "vjcvt", "VjcvtSFixedFpD", "FpRegRegOp",
            { "code": vjcvtSFixedFpDCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vjcvtSFixedFpDIop);
    decoder_output += FpRegRegOpConstructor.subst(vjcvtSFixedFpDIop);
    exec_output += PredOpExecute.subst(vjcvtSFixedFpDIop);

    vcvtFpUIntSRCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        vfpFlushToZero(fpscr, FpOp1);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_uw = vfpFpToFixed<float>(FpOp1, false, 32, 0, false);
        __asm__ __volatile__("" :: "m" (FpDest_uw));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpUIntSRIop = ArmInstObjParams("vcvt", "VcvtFpUIntSR", "FpRegRegOp",
                                       { "code": vcvtFpUIntSRCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpUIntSRIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntSRIop);
    exec_output += PredOpExecute.subst(vcvtFpUIntSRIop);

    vcvtFpUIntDRCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        uint64_t result = vfpFpToFixed<double>(cOp1, false, 32, 0, false);
        __asm__ __volatile__("" :: "m" (result));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = result;
        FpscrExc = fpscr;
    '''
    vcvtFpUIntDRIop = ArmInstObjParams("vcvtr", "VcvtFpUIntDR", "FpRegRegOp",
                                       { "code": vcvtFpUIntDRCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpUIntDRIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntDRIop);
    exec_output += PredOpExecute.subst(vcvtFpUIntDRIop);

    vcvtFpSIntSRCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        vfpFlushToZero(fpscr, FpOp1);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_sw = vfpFpToFixed<float>(FpOp1, true, 32, 0, false);
        __asm__ __volatile__("" :: "m" (FpDest_sw));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpSIntSRIop = ArmInstObjParams("vcvtr", "VcvtFpSIntSR", "FpRegRegOp",
                                       { "code": vcvtFpSIntSRCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpSIntSRIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntSRIop);
    exec_output += PredOpExecute.subst(vcvtFpSIntSRIop);

    vcvtFpSIntDRCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        int64_t result = vfpFpToFixed<double>(cOp1, true, 32, 0, false);
        __asm__ __volatile__("" :: "m" (result));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = result;
        FpscrExc = fpscr;
    '''
    vcvtFpSIntDRIop = ArmInstObjParams("vcvtr", "VcvtFpSIntDR", "FpRegRegOp",
                                       { "code": vcvtFpSIntDRCode,
                                         "predicate_test": predicateTest,
                                         "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpSIntDRIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntDRIop);
    exec_output += PredOpExecute.subst(vcvtFpSIntDRIop);

    round_mode_suffix_to_mode = {
        '': 'VfpRoundZero',
        'a': 'VfpRoundAway',
        'm': 'VfpRoundDown',
        'n': 'VfpRoundNearest',
        'p': 'VfpRoundUpward',
    }

    def buildVcvt(code, className, roundModeSuffix):
        global header_output, decoder_output, exec_output, \
            vfpEnabledCheckCode, round_mode_suffix_to_mode
        full_code = vfpEnabledCheckCode + code.format(
            round_mode=round_mode_suffix_to_mode[roundModeSuffix],
        )
        iop = ArmInstObjParams(
            "vcvt{}".format(roundModeSuffix),
            className.format(roundModeSuffix),
            "FpRegRegOp",
            { "code": full_code,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" },
            []
        )
        header_output += FpRegRegOpDeclare.subst(iop);
        decoder_output += FpRegRegOpConstructor.subst(iop);
        exec_output += PredOpExecute.subst(iop);

    code = '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        gem5::RoundingMode old_rm = gem5::getFpRound();
        gem5::setFpRound(gem5::RoundingMode::TowardZero);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_uw = vfpFpToFixed<float>(
            FpOp1, false, 32, 0, true, {round_mode});
        __asm__ __volatile__("" :: "m" (FpDest_uw));
        gem5::setFpRound(old_rm);
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    for round_mode_suffix in round_mode_suffix_to_mode:
        buildVcvt(code, "Vcvt{}FpUIntS", round_mode_suffix)

    code = '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        gem5::RoundingMode old_rm = gem5::getFpRound();
        gem5::setFpRound(gem5::RoundingMode::TowardZero);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        uint64_t result = vfpFpToFixed<double>(
            cOp1, false, 32, 0, true, {round_mode});
        __asm__ __volatile__("" :: "m" (result));
        gem5::setFpRound(old_rm);
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = result;
        FpscrExc = fpscr;
    '''
    for round_mode_suffix in round_mode_suffix_to_mode:
        buildVcvt(code, "Vcvt{}FpUIntD", round_mode_suffix)

    code = '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        gem5::RoundingMode old_rm = gem5::getFpRound();
        gem5::setFpRound(gem5::RoundingMode::TowardZero);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_sw = vfpFpToFixed<float>(
            FpOp1, true, 32, 0, true, {round_mode});
        __asm__ __volatile__("" :: "m" (FpDest_sw));
        gem5::setFpRound(old_rm);
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    for round_mode_suffix in round_mode_suffix_to_mode:
        buildVcvt(code, "Vcvt{}FpSIntS", round_mode_suffix)

    code = '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        gem5::RoundingMode old_rm = gem5::getFpRound();
        gem5::setFpRound(gem5::RoundingMode::TowardZero);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        int64_t result = vfpFpToFixed<double>(
            cOp1, true, 32, 0, true, {round_mode});
        __asm__ __volatile__("" :: "m" (result));
        gem5::setFpRound(old_rm);
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = result;
        FpscrExc = fpscr;
    '''
    for round_mode_suffix in round_mode_suffix_to_mode:
        buildVcvt(code, "Vcvt{}FpSIntD", round_mode_suffix)

    vcvtFpSFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        double cDest = fixFpSFpDDest(FpscrExc, FpOp1);
        __asm__ __volatile__("" :: "m" (cDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = dblLow(cDest);
        FpDestP1_uw = dblHi(cDest);
        FpscrExc = fpscr;
    '''
    vcvtFpSFpDIop = ArmInstObjParams("vcvt", "VcvtFpSFpD", "FpRegRegOp",
                                     { "code": vcvtFpSFpDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpSFpDIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpDIop);
    exec_output += PredOpExecute.subst(vcvtFpSFpDIop);

    vcvtFpDFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        FpDest = fixFpDFpSDest(FpscrExc, cOp1);
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpDFpSIop = ArmInstObjParams("vcvt", "VcvtFpDFpS", "FpRegRegOp",
                                     { "code": vcvtFpDFpSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpDFpSIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpDFpSIop);
    exec_output += PredOpExecute.subst(vcvtFpDFpSIop);

    vcvtFpHTFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest = vcvtFpHFpS(fpscr, fpscr.dn, fpscr.ahp,
                            bits(fpToBits(FpOp1), 31, 16));
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpHTFpSIop = ArmInstObjParams("vcvtt", "VcvtFpHTFpS", "FpRegRegOp",
                                      { "code": vcvtFpHTFpSCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpHTFpSIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpHTFpSIop);
    exec_output += PredOpExecute.subst(vcvtFpHTFpSIop);

    vcvtFpHBFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest = vcvtFpHFpS(fpscr, fpscr.dn, fpscr.ahp,
                            bits(fpToBits(FpOp1), 15, 0));
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpHBFpSIop = ArmInstObjParams("vcvtb", "VcvtFpHBFpS", "FpRegRegOp",
                                      { "code": vcvtFpHBFpSCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpHBFpSIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpHBFpSIop);
    exec_output += PredOpExecute.subst(vcvtFpHBFpSIop);

    vcvtFpSFpHTCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1), "=m" (FpDest_uw)
                                : "m" (FpOp1), "m" (FpDest_uw));
        FpDest_uw = insertBits(FpDest_uw, 31, 16,,
                               vcvtFpSFpH(fpscr, fpscr.fz, fpscr.dn,
                               fpscr.rMode, fpscr.ahp, FpOp1));
        __asm__ __volatile__("" :: "m" (FpDest_uw));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpSFpHTIop = ArmInstObjParams("vcvtt", "VcvtFpSFpHT", "FpRegRegOp",
                                      { "code": vcvtFpHTFpSCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpSFpHTIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpHTIop);
    exec_output += PredOpExecute.subst(vcvtFpSFpHTIop);

    vcvtFpSFpHBCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1), "=m" (FpDest_uw)
                                : "m" (FpOp1), "m" (FpDest_uw));
        FpDest_uw = insertBits(FpDest_uw, 15, 0,
                               vcvtFpSFpH(fpscr, fpscr.fz, fpscr.dn,
                               fpscr.rMode, fpscr.ahp, FpOp1));
        __asm__ __volatile__("" :: "m" (FpDest_uw));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpSFpHBIop = ArmInstObjParams("vcvtb", "VcvtFpSFpHB", "FpRegRegOp",
                                      { "code": vcvtFpSFpHBCode,
                                        "predicate_test": predicateTest,
                                        "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcvtFpSFpHBIop);
    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpHBIop);
    exec_output += PredOpExecute.subst(vcvtFpSFpHBIop);

    vcmpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpDest, FpOp1);
        if (FpDest == FpOp1) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (FpDest < FpOp1) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (FpDest > FpOp1) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            const uint32_t qnan = 0x7fc00000;
            const bool nan1 = std::isnan(FpDest);
            const bool signal1 = nan1 && ((fpToBits(FpDest) & qnan) != qnan);
            const bool nan2 = std::isnan(FpOp1);
            const bool signal2 = nan2 && ((fpToBits(FpOp1) & qnan) != qnan);
            if (signal1 || signal2)
                fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpSIop = ArmInstObjParams("vcmps", "VcmpS", "FpRegRegOp",
                                     { "code": vcmpSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcmpSIop);
    decoder_output += FpRegRegOpConstructor.subst(vcmpSIop);
    exec_output += PredOpExecute.subst(vcmpSIop);

    vcmpDCode = vfpEnabledCheckCode + '''
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, cDest, cOp1);
        if (cDest == cOp1) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (cDest < cOp1) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (cDest > cOp1) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            const uint64_t qnan = 0x7ff8000000000000ULL;
            const bool nan1 = std::isnan(cDest);
            const bool signal1 = nan1 && ((fpToBits(cDest) & qnan) != qnan);
            const bool nan2 = std::isnan(cOp1);
            const bool signal2 = nan2 && ((fpToBits(cOp1) & qnan) != qnan);
            if (signal1 || signal2)
                fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpDIop = ArmInstObjParams("vcmpd", "VcmpD", "FpRegRegOp",
                                     { "code": vcmpDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcmpDIop);
    decoder_output += FpRegRegOpConstructor.subst(vcmpDIop);
    exec_output += PredOpExecute.subst(vcmpDIop);

    vcmpZeroSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpDest);
        // This only handles imm == 0 for now.
        assert(imm == 0);
        if (FpDest == imm) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (FpDest < imm) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (FpDest > imm) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            const uint32_t qnan = 0x7fc00000;
            const bool nan = std::isnan(FpDest);
            const bool signal = nan && ((fpToBits(FpDest) & qnan) != qnan);
            if (signal)
                fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpZeroSIop = ArmInstObjParams("vcmpZeros", "VcmpZeroS", "FpRegImmOp",
                                     { "code": vcmpZeroSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegImmOpDeclare.subst(vcmpZeroSIop);
    decoder_output += FpRegImmOpConstructor.subst(vcmpZeroSIop);
    exec_output += PredOpExecute.subst(vcmpZeroSIop);

    vcmpZeroDCode = vfpEnabledCheckCode + '''
        // This only handles imm == 0 for now.
        assert(imm == 0);
        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, cDest);
        if (cDest == imm) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (cDest < imm) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (cDest > imm) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            const uint64_t qnan = 0x7ff8000000000000ULL;
            const bool nan = std::isnan(cDest);
            const bool signal = nan && ((fpToBits(cDest) & qnan) != qnan);
            if (signal)
                fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpZeroDIop = ArmInstObjParams("vcmpZerod", "VcmpZeroD", "FpRegImmOp",
                                     { "code": vcmpZeroDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegImmOpDeclare.subst(vcmpZeroDIop);
    decoder_output += FpRegImmOpConstructor.subst(vcmpZeroDIop);
    exec_output += PredOpExecute.subst(vcmpZeroDIop);

    vcmpeSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpDest, FpOp1);
        if (FpDest == FpOp1) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (FpDest < FpOp1) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (FpDest > FpOp1) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpeSIop = ArmInstObjParams("vcmpes", "VcmpeS", "FpRegRegOp",
                                     { "code": vcmpeSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcmpeSIop);
    decoder_output += FpRegRegOpConstructor.subst(vcmpeSIop);
    exec_output += PredOpExecute.subst(vcmpeSIop);

    vcmpeDCode = vfpEnabledCheckCode + '''
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, cDest, cOp1);
        if (cDest == cOp1) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (cDest < cOp1) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (cDest > cOp1) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpeDIop = ArmInstObjParams("vcmped", "VcmpeD", "FpRegRegOp",
                                     { "code": vcmpeDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegRegOpDeclare.subst(vcmpeDIop);
    decoder_output += FpRegRegOpConstructor.subst(vcmpeDIop);
    exec_output += PredOpExecute.subst(vcmpeDIop);

    vcmpeZeroSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpDest);
        if (FpDest == imm) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (FpDest < imm) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (FpDest > imm) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpeZeroSIop = ArmInstObjParams("vcmpeZeros", "VcmpeZeroS", "FpRegImmOp",
                                     { "code": vcmpeZeroSCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegImmOpDeclare.subst(vcmpeZeroSIop);
    decoder_output += FpRegImmOpConstructor.subst(vcmpeZeroSIop);
    exec_output += PredOpExecute.subst(vcmpeZeroSIop);

    vcmpeZeroDCode = vfpEnabledCheckCode + '''
        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, cDest);
        if (cDest == imm) {
            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
        } else if (cDest < imm) {
            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
        } else if (cDest > imm) {
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
        } else {
            fpscr.ioc = 1;
            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
        }
        FpCondCodes = fpscr & FpCondCodesMask;
        FpscrExc = fpscr;
    '''
    vcmpeZeroDIop = ArmInstObjParams("vcmpeZerod", "VcmpeZeroD", "FpRegImmOp",
                                     { "code": vcmpeZeroDCode,
                                       "predicate_test": predicateTest,
                                       "op_class": "SimdFloatCmpOp" }, [])
    header_output += FpRegImmOpDeclare.subst(vcmpeZeroDIop);
    decoder_output += FpRegImmOpConstructor.subst(vcmpeZeroDIop);
    exec_output += PredOpExecute.subst(vcmpeZeroDIop);
}};

let {{

    header_output = ""
    decoder_output = ""
    exec_output = ""

    vselSCode = vfpEnabledCheckCode + '''
        if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, cond)) {
            FpDest = FpOp1;
        } else {
            FpDest = FpOp2;
        } '''

    vselSIop = ArmInstObjParams("vsels", "VselS", "FpRegRegRegCondOp",
                                { "code" : vselSCode,
                                  "predicate_test" : predicateTest,
                                  "op_class" : "SimdFloatCmpOp" }, [] )
    header_output += FpRegRegRegCondOpDeclare.subst(vselSIop);
    decoder_output += FpRegRegRegCondOpConstructor.subst(vselSIop);
    exec_output +=  PredOpExecute.subst(vselSIop);

    vselDCode = vfpEnabledCheckCode + '''
        if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, cond)) {
            FpDestP0_uw = FpOp1P0_uw;
            FpDestP1_uw = FpOp1P1_uw;
        } else {
            FpDestP0_uw = FpOp2P0_uw;
            FpDestP1_uw = FpOp2P1_uw;
        } '''

    vselDIop = ArmInstObjParams("vseld", "VselD", "FpRegRegRegCondOp",
                                { "code" : vselDCode,
                                  "predicate_test" : predicateTest,
                                  "op_class" : "SimdFloatCmpOp" }, [] )
    header_output += FpRegRegRegCondOpDeclare.subst(vselDIop);
    decoder_output += FpRegRegRegCondOpConstructor.subst(vselDIop);
    exec_output +=  PredOpExecute.subst(vselDIop);
}};


let {{

    header_output = ""
    decoder_output = ""
    exec_output = ""

    vcvtFpSFixedSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_sw = vfpFpToFixed<float>(FpOp1, true, 32, imm);
        __asm__ __volatile__("" :: "m" (FpDest_sw));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpSFixedSIop = ArmInstObjParams(
            "vcvt", "VcvtFpSFixedS", "FpRegRegImmOp",
            { "code": vcvtFpSFixedSCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSFixedSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSFixedSIop);
    exec_output += PredOpExecute.subst(vcvtFpSFixedSIop);

    vcvtFpSFixedDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        uint64_t mid = vfpFpToFixed<double>(cOp1, true, 32, imm);
        __asm__ __volatile__("" :: "m" (mid));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = mid;
        FpDestP1_uw = mid >> 32;
        FpscrExc = fpscr;
    '''
    vcvtFpSFixedDIop = ArmInstObjParams(
            "vcvt", "VcvtFpSFixedD", "FpRegRegImmOp",
            { "code": vcvtFpSFixedDCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSFixedDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSFixedDIop);
    exec_output += PredOpExecute.subst(vcvtFpSFixedDIop);

    vcvtFpUFixedSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_uw = vfpFpToFixed<float>(FpOp1, false, 32, imm);
        __asm__ __volatile__("" :: "m" (FpDest_uw));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpUFixedSIop = ArmInstObjParams(
            "vcvt", "VcvtFpUFixedS", "FpRegRegImmOp",
            { "code": vcvtFpUFixedSCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUFixedSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUFixedSIop);
    exec_output += PredOpExecute.subst(vcvtFpUFixedSIop);

    vcvtFpUFixedDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        uint64_t mid = vfpFpToFixed<double>(cOp1, false, 32, imm);
        __asm__ __volatile__("" :: "m" (mid));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = mid;
        FpDestP1_uw = mid >> 32;
        FpscrExc = fpscr;
    '''
    vcvtFpUFixedDIop = ArmInstObjParams(
            "vcvt", "VcvtFpUFixedD", "FpRegRegImmOp",
            { "code": vcvtFpUFixedDCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUFixedDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUFixedDIop);
    exec_output += PredOpExecute.subst(vcvtFpUFixedDIop);

    vcvtSFixedFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1_sw) : "m" (FpOp1_sw));
        FpDest = vfpSFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_sw, 32, imm);
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtSFixedFpSIop = ArmInstObjParams(
            "vcvt", "VcvtSFixedFpS", "FpRegRegImmOp",
            { "code": vcvtSFixedFpSCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtSFixedFpSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSFixedFpSIop);
    exec_output += PredOpExecute.subst(vcvtSFixedFpSIop);

    vcvtSFixedFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
        double cDest = vfpSFixedToFpD(fpscr.fz, fpscr.dn, mid, 32, imm);
        __asm__ __volatile__("" :: "m" (cDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = dblLow(cDest);
        FpDestP1_uw = dblHi(cDest);
        FpscrExc = fpscr;
    '''
    vcvtSFixedFpDIop = ArmInstObjParams(
            "vcvt", "VcvtSFixedFpD", "FpRegRegImmOp",
            { "code": vcvtSFixedFpDCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtSFixedFpDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSFixedFpDIop);
    exec_output += PredOpExecute.subst(vcvtSFixedFpDIop);

    vcvtUFixedFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1_uw) : "m" (FpOp1_uw));
        FpDest = vfpUFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_uw, 32, imm);
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtUFixedFpSIop = ArmInstObjParams(
            "vcvt", "VcvtUFixedFpS", "FpRegRegImmOp",
            { "code": vcvtUFixedFpSCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtUFixedFpSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUFixedFpSIop);
    exec_output += PredOpExecute.subst(vcvtUFixedFpSIop);

    vcvtUFixedFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
        double cDest = vfpUFixedToFpD(fpscr.fz, fpscr.dn, mid, 32, imm);
        __asm__ __volatile__("" :: "m" (cDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = dblLow(cDest);
        FpDestP1_uw = dblHi(cDest);
        FpscrExc = fpscr;
    '''
    vcvtUFixedFpDIop = ArmInstObjParams(
            "vcvt", "VcvtUFixedFpD", "FpRegRegImmOp",
            { "code": vcvtUFixedFpDCode,
              "predicate_test": predicateTest,
              "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtUFixedFpDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUFixedFpDIop);
    exec_output += PredOpExecute.subst(vcvtUFixedFpDIop);

    vcvtFpSHFixedSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_sh = vfpFpToFixed<float>(FpOp1, true, 16, imm);
        __asm__ __volatile__("" :: "m" (FpDest_sh));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpSHFixedSIop = ArmInstObjParams("vcvt", "VcvtFpSHFixedS",
                                         "FpRegRegImmOp",
                                         { "code": vcvtFpSHFixedSCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSHFixedSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSHFixedSIop);
    exec_output += PredOpExecute.subst(vcvtFpSHFixedSIop);

    vcvtFpSHFixedDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        uint64_t result = vfpFpToFixed<double>(cOp1, true, 16, imm);
        __asm__ __volatile__("" :: "m" (result));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = result;
        FpDestP1_uw = result >> 32;
        FpscrExc = fpscr;
    '''
    vcvtFpSHFixedDIop = ArmInstObjParams("vcvt", "VcvtFpSHFixedD",
                                         "FpRegRegImmOp",
                                         { "code": vcvtFpSHFixedDCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSHFixedDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSHFixedDIop);
    exec_output += PredOpExecute.subst(vcvtFpSHFixedDIop);

    vcvtFpUHFixedSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        vfpFlushToZero(fpscr, FpOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
        FpDest_uh = vfpFpToFixed<float>(FpOp1, false, 16, imm);
        __asm__ __volatile__("" :: "m" (FpDest_uh));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtFpUHFixedSIop = ArmInstObjParams("vcvt", "VcvtFpUHFixedS",
                                         "FpRegRegImmOp",
                                         { "code": vcvtFpUHFixedSCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUHFixedSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUHFixedSIop);
    exec_output += PredOpExecute.subst(vcvtFpUHFixedSIop);

    vcvtFpUHFixedDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
        vfpFlushToZero(fpscr, cOp1);
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
        uint64_t mid = vfpFpToFixed<double>(cOp1, false, 16, imm);
        __asm__ __volatile__("" :: "m" (mid));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = mid;
        FpDestP1_uw = mid >> 32;
        FpscrExc = fpscr;
    '''
    vcvtFpUHFixedDIop = ArmInstObjParams("vcvt", "VcvtFpUHFixedD",
                                         "FpRegRegImmOp",
                                         { "code": vcvtFpUHFixedDCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUHFixedDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUHFixedDIop);
    exec_output += PredOpExecute.subst(vcvtFpUHFixedDIop);

    vcvtSHFixedFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1_sh) : "m" (FpOp1_sh));
        FpDest = vfpSFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_sh, 16, imm);
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtSHFixedFpSIop = ArmInstObjParams("vcvt", "VcvtSHFixedFpS",
                                         "FpRegRegImmOp",
                                         { "code": vcvtSHFixedFpSCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtSHFixedFpSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSHFixedFpSIop);
    exec_output += PredOpExecute.subst(vcvtSHFixedFpSIop);

    vcvtSHFixedFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
        double cDest = vfpSFixedToFpD(fpscr.fz, fpscr.dn, mid, 16, imm);
        __asm__ __volatile__("" :: "m" (cDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = dblLow(cDest);
        FpDestP1_uw = dblHi(cDest);
        FpscrExc = fpscr;
    '''
    vcvtSHFixedFpDIop = ArmInstObjParams("vcvt", "VcvtSHFixedFpD",
                                         "FpRegRegImmOp",
                                         { "code": vcvtSHFixedFpDCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtSHFixedFpDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSHFixedFpDIop);
    exec_output += PredOpExecute.subst(vcvtSHFixedFpDIop);

    vcvtUHFixedFpSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (FpOp1_uh) : "m" (FpOp1_uh));
        FpDest = vfpUFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_uh, 16, imm);
        __asm__ __volatile__("" :: "m" (FpDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpscrExc = fpscr;
    '''
    vcvtUHFixedFpSIop = ArmInstObjParams("vcvt", "VcvtUHFixedFpS",
                                         "FpRegRegImmOp",
                                         { "code": vcvtUHFixedFpSCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtUHFixedFpSIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUHFixedFpSIop);
    exec_output += PredOpExecute.subst(vcvtUHFixedFpSIop);

    vcvtUHFixedFpDCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
        VfpSavedState state = prepFpState(fpscr.rMode);
        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
        double cDest = vfpUFixedToFpD(fpscr.fz, fpscr.dn, mid, 16, imm);
        __asm__ __volatile__("" :: "m" (cDest));
        finishVfp(fpscr, state, fpscr.fz);
        FpDestP0_uw = dblLow(cDest);
        FpDestP1_uw = dblHi(cDest);
        FpscrExc = fpscr;
    '''
    vcvtUHFixedFpDIop = ArmInstObjParams("vcvt", "VcvtUHFixedFpD",
                                         "FpRegRegImmOp",
                                         { "code": vcvtUHFixedFpDCode,
                                           "predicate_test": predicateTest,
                                           "op_class": "SimdFloatCvtOp" }, [])
    header_output += FpRegRegImmOpDeclare.subst(vcvtUHFixedFpDIop);
    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUHFixedFpDIop);
    exec_output += PredOpExecute.subst(vcvtUHFixedFpDIop);
}};
